home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / plotting / imagetoo / imagetl1.lha / Imagetool / HDF / dfimcomp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-20  |  35.6 KB  |  1,256 lines

  1. /*****************************************************************************
  2. *              NCSA HDF version 3.10
  3. *                July 1, 1990
  4. *
  5. * NCSA HDF Version 3.10 source code and documentation are in the public
  6. * domain.  Specifically, we give to the public domain all rights for future
  7. * licensing of the source code, all resale rights, and all publishing rights.
  8. * We ask, but do not require, that the following message be included in all
  9. * derived works:
  10. * Portions developed at the National Center for Supercomputing Applications at
  11. * the University of Illinois at Urbana-Champaign.
  12. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  13. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  14. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  15. *****************************************************************************/
  16.  
  17. #ifdef RCSID
  18. static char RcsId[] = "@(#)$Revision: 3.4 $";
  19. #endif
  20. /*
  21. $Header: /pita/work/HDF/dev/RCS/src/dfimcomp.c,v 3.4 90/07/02 10:12:07 clow beta $
  22.  
  23. $Log:    dfimcomp.c,v $
  24.  * Revision 3.4  90/07/02  10:12:07  clow
  25.  * some cosmetic modifications
  26.  * 
  27. */
  28. /************************************************************************/
  29. /*  Module Name : imcomp                        */
  30. /*  Exports     : DFCimcomp(), DFCunimcomp()                */
  31. /*  Purpose     : Compresses color images               */
  32. /*  Author  : Eng-Kiat Koh                      */
  33. /*  Date    : June 30th, 1988                   */
  34. /*  Functions   : DFCimcomp(), compress(), init_global(), cnt_color()   */
  35. /*        set_palette(), fillin_color(), map(), nearest_color() */
  36. /*        DFCunimcomp(), sqr()                                  */
  37. /************************************************************************/
  38.  
  39.  
  40. #include "df.h"
  41.  
  42. #define PALSIZE 256
  43. #define BIT8 0
  44. #define BIT24 1
  45.  
  46. #ifndef MAC
  47. #define MAXCOLOR 32768
  48. #else /*MAC*/
  49. #define MAXCOLOR 768
  50. #endif /*MAC*/
  51.  
  52. #ifndef NULL
  53. #   define NULL 0
  54. #endif
  55.  
  56. #define RED 0
  57. #define GREEN 1
  58. #define BLUE 2
  59. #define EPSILON 0.5
  60. #define LO 1
  61. #define HI 0
  62.  
  63. struct rgb
  64. {
  65.   unsigned char c[3];
  66. };
  67.  
  68. struct box
  69. {
  70.   float bnd[3][2];
  71.   int *pts;
  72.   int nmbr_pts;
  73.   int nmbr_distinct;
  74.   struct box *left;
  75.   struct box *right;
  76. };
  77.  
  78.  
  79. unsigned char *new_pal;          /* pointer to new palette           */
  80.  
  81.  
  82. static int *hist = (int *)NULL;    /* histogram for distinct colors    */
  83. static struct box *frontier = (struct box *)NULL; /* pointer to the */
  84.                           /* list of boxes */
  85. static struct rgb *distinct_pt = (struct rgb *)NULL; /* contains all */
  86.                              /* distinct rgb points */
  87.  
  88. static void sel_palette();
  89. static void compress();
  90. static void init_global();
  91. static int cnt_color();
  92. static void set_palette();
  93. static void fillin_color();
  94. static int indx();
  95. static void map();
  96. static int nearest_color();
  97. static long int sqr();
  98. static void init();
  99. static int partition();
  100. static struct box *find_box();
  101. static void split_box();
  102. static void assign_color();
  103. static int select_dim();
  104. static float find_med();
  105. static void classify();
  106. static int next_pt();
  107.  
  108. /* extern char *calloc(); */
  109.  
  110. static struct rgb *color_pt = (struct rgb *)NULL; /*contains the hi-lo */
  111.                           /*colors for each block*/
  112. static unsigned char *image;    /* contains the compressed image            */
  113. static int trans[MAXCOLOR];     /* color translation table                  */
  114.  
  115. /************************************************************************/
  116. /*  Function    : DFCimcomp                                             */
  117. /*  Purpose : Performs Imcomp Compression                           */
  118. /*  Parameters  :                                                       */
  119. /*    xdim, ydim - dimensions of image                                  */
  120. /*                 IT IS ASSUMED THAT THE DIMENSIONS ARE A MULTIPLE OF 4*/
  121. /*    in, out    - input image array and output image buffer size of in */
  122. /*                 is xdim*ydim bytes for 8 bit per pixel mode. It is 3 */
  123. /*                 times that for 24 bits per pixel mode. The output    */
  124. /*                 buffer is always (xdim*ydim)/4.                      */
  125. /*    in_pal     - input palette. Consist of rgb triples unlike seq-type*/
  126. /*                 palette. This is a NULL pointer if operating at the  */
  127. /*                 24 bit per pixel mode.                               */
  128. /*    out_pal    - output palette. Consist of PALSIZE color entries.    */
  129. /*                 each entry is an rgb triple.                         */
  130. /*    mode       - Either BIT8 or BIT24                                 */
  131. /*  Returns     : none                          */
  132. /*  Called by   : External routines                                     */
  133. /*  Calls       : init_global(), compress(), cnt_color(), set_palette(),*/
  134. /*        sel_palette(), map()                                  */
  135. /************************************************************************/
  136.  
  137. void DFCimcomp(xdim, ydim, in, out, in_pal, out_pal, mode)
  138. int32 xdim, ydim;
  139. int mode;
  140. char in[], out[], in_pal[], out_pal[];
  141. {
  142.   unsigned char raster[48];
  143.   int blocks, nmbr, i, j, k, l, x, y;
  144.   void init_global();
  145.   void compress();
  146.   int cnt_color();
  147.   void set_palette();
  148.   void sel_palette();
  149.   void map();
  150.   void fillin_color();
  151.  
  152.   init_global(xdim, ydim, out, out_pal);
  153.  
  154.   /* compress pixel blocks */
  155.   blocks = 0;
  156.   for (i=0; i<(ydim/4); i++)
  157.     for (j=0; j<(xdim/4); j++)
  158.     {
  159.       switch (mode)
  160.       {
  161.         case BIT8 : /* 8 bit per pixel format */
  162.             k = 0;
  163.             for (y=(i*4); y<(i*4+4); y++)
  164.               for (x=(j*4); x<(j*4+4); x++)         
  165.               {
  166.             l = y*xdim + x;
  167.             raster[k++] = (unsigned char) in_pal[3 * (unsigned char)in[l]];
  168.             raster[k++] = (unsigned char) in_pal[3 * (unsigned char)in[l] + 1];
  169.             raster[k++] = (unsigned char) in_pal[3 * (unsigned char)in[l] + 2];
  170.               } /* end of for x */
  171.             compress(raster,blocks);
  172.             break;
  173.  
  174.       case BIT24: /* 24 bit per pixel format */
  175.             k = 0;
  176.             for (y=(i*4); y<(i*4+4); y++)
  177.               for (x=(j*4); x<(j*4+4); x++)         
  178.               {
  179.             l = 3 *(y*xdim + x);
  180.             raster[k++] = (unsigned char) in[l];
  181.             raster[k++] = (unsigned char) in[l+1];
  182.             raster[k++] = (unsigned char) in[l+2];
  183.               } /* end of for x */
  184.             compress(raster,blocks);
  185.             break;
  186.     
  187.     default   : /* unsupported format */
  188.             printf("Error : Unsupported Format \n");
  189.             exit(1);
  190.             break;
  191.       } /* end of switch */
  192.       
  193.       blocks++;
  194.     } /* end of for j */
  195.  
  196.   /* set palette */
  197.   nmbr = cnt_color(blocks);
  198. /*
  199.   printf("Number of colors %d \n", nmbr);
  200. */
  201.   if (nmbr <= PALSIZE)
  202.     set_palette(blocks);
  203.   else
  204.   {
  205.     sel_palette(blocks,nmbr,color_pt);
  206.     map(blocks);
  207.   }
  208.  
  209.   fillin_color(blocks);
  210.  
  211. } /* end of DFCimcomp */
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218. /************************************************************************/
  219. /*  Function    : compress                                  */
  220. /*  Purpose : Given a block of 16 pixels, sets up a 16 bit bitmap   */
  221. /*                and assigns a lo and hi color for the block. For block*/
  222. /*                i, hi color is stored in color_pt[2i] and lo in       */
  223. /*                color_pt[2i+1]. Each color is then reduced to 15 bits */
  224. /*                by truncating the lower order 3 bits of each component*/
  225. /*  Parameter   :                           */
  226. /*    raster     - contains the 16 pixels of a block. Each pixel is 3   */
  227. /*         bytes, 1 byte for each color component               */
  228. /*    block  - pixel block number                                   */
  229. /*  Returns     : none                                                  */
  230. /*  Called by   : DFCimcomp()                       */
  231. /*  Calls       : none                          */
  232. /************************************************************************/
  233.  
  234. static void compress(raster, block)
  235. unsigned char raster[];
  236. int block;
  237. {
  238.   float y[16], y_av;
  239.   int i, j, k, l, bit;
  240.   int high, hi, lo;
  241.   int c_hi[3], c_lo[3];
  242.  
  243.   /* calculate luminance */
  244.   y_av = 0.0;
  245.   for (i=0; i<16; i++)
  246.   {
  247.     j = 3*i;
  248.     y[i] = 0.3*(float)raster[j] + 0.59*(float)raster[j+1] + 
  249.            0.11*(float)raster[j+2];
  250. /*    printf("compress: y[%d] is %f\n",i,y[i]);*/
  251.     y_av = y_av + y[i];
  252.   }
  253.   y_av = y_av / 16.0;
  254. /*  printf("y_av is %f\n",y_av); */
  255.  
  256.   /* initialize c_hi and c_lo */
  257.   for (i=RED; i<=BLUE; i++)
  258.   {
  259.     c_hi[i] = 0;
  260.     c_lo[i] = 0;
  261.   }
  262.  
  263.   /* build bit map */
  264.   k = 4 * block;
  265.   high = 0;
  266.   hi = 2 * block;
  267.   lo = hi + 1;
  268.   for (i=0; i<2; i++)
  269.   {
  270.     bit = 128;
  271.     for (j = (i*8); j<(i*8+8); j++)
  272.     {
  273.       if (y[j] > y_av)
  274.       {
  275.     image[k] = image[k] | bit;
  276.     high++;
  277.         for (l=RED; l<= BLUE; l++)
  278.       c_hi[l] = c_hi[l] + (int)raster[3*j+l];
  279.       }
  280.       else
  281.       {
  282.     for (l=RED; l<=BLUE; l++)
  283.           c_lo[l] = c_lo[l] + (int)raster[3*j+l];
  284.       } /* end of if */
  285.  
  286.       bit = bit >> 1;
  287.     } /* end of for j */
  288.    
  289.     k++;
  290.   } /* end of for i */
  291.  
  292.   /* calculate hi lo color */
  293.   for (i=RED; i<=BLUE; i++)
  294.   {
  295.     if (high != 0)
  296.       color_pt[hi].c[i] = (int)((float)c_hi[i] / (float)high);
  297.     if (high != 16)
  298.       color_pt[lo].c[i] = (int)((float)c_lo[i] / (float)(16 - high));
  299.     color_pt[hi].c[i] = color_pt[hi].c[i] >> 3;
  300.     color_pt[lo].c[i] = color_pt[lo].c[i] >> 3;
  301.  
  302.   }
  303. } /* end of compress */
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310. /************************************************************************/
  311. /*  Function    : init_global                       */
  312. /*  Purpose : Allocates memory for global variables                 */
  313. /*  Parameter   :                           */
  314. /*    xdim, ydim - x and y dimension of image               */
  315. /*    out        - pointer to output buffer                             */
  316. /*    out_pal    - pointer to output palette                            */
  317. /*  Returns     : none                              */
  318. /*  Called by   : DFCimcomp()                       */
  319. /*  Calls       : none                          */
  320. /************************************************************************/
  321.  
  322. static void init_global(xdim, ydim, out, out_pal)
  323. int32 xdim, ydim;
  324. char *out, *out_pal;
  325. {
  326.   int i, j;
  327.  
  328.   /* allocate memory */
  329.   image = (unsigned char *) out;
  330.   new_pal = (unsigned char *) out_pal;
  331.   if (color_pt) DFIfreespace((char *) color_pt);
  332.   color_pt = (struct rgb *)DFIgetspace((unsigned)((xdim*ydim)/8) *
  333.                        sizeof(struct rgb));
  334.  
  335.   if (image == NULL || color_pt == NULL || new_pal == NULL)
  336.   {
  337.     printf("Error : Out of Memory\n");
  338.     exit(1);
  339.   }
  340.  
  341.   /* initialize */
  342.   for (i=0; i<(xdim*ydim/4); i++)
  343.     image[i] = 0;
  344.  
  345.   for (i=0; i<(xdim*ydim/8); i++)
  346.     for (j=RED; j<= BLUE; j++)
  347.       color_pt[i].c[j] = 0;
  348.  
  349.   for (i=0; i<MAXCOLOR; i++)
  350.     trans[i] = -1;
  351. } /* end of init_global */
  352.  
  353.  
  354.  
  355.  
  356.  
  357. /************************************************************************/
  358. /*  Function    : cnt_color                                 */
  359. /*  Purpose : Counts the number of distinct colors compressd image  */
  360. /*  Parameter   :                           */
  361. /*    blocks     - total number of pixel blocks             */
  362. /*  Returns     : Number of distinct colors                             */
  363. /*  Called by   : DFCimcomp()                                           */
  364. /*  Calls       : indx()                        */
  365. /************************************************************************/
  366.  
  367. static int cnt_color(blocks)
  368. int blocks;
  369. {
  370.   int temp[MAXCOLOR];
  371.   int i, k, count;
  372.   int indx();
  373.  
  374.   for (i=0; i<MAXCOLOR; i++)
  375.     temp[i] = -1;
  376.  
  377.   for (i=0; i<(2*blocks); i++)
  378.   {
  379.     k = indx(color_pt[i].c[RED],color_pt[i].c[GREEN],color_pt[i].c[BLUE]);
  380. /*    printf("cnt_color: k is %d\n",k); */
  381.     temp[k] = 0;
  382.   }
  383.  
  384.   count  = 0;
  385.   for (i = 0; i< MAXCOLOR; i++)
  386.     if (temp[i] == 0)
  387.       count++;
  388.  
  389.   return count;
  390. } /* end of cnt_color */
  391.  
  392.  
  393.  
  394.  
  395.  
  396. /************************************************************************/
  397. /*  Function    : set_palette                       */
  398. /*  Purpose : The number of distinct colors is less than the desired*/
  399. /*                output palette size. Therefore each distinct color can*/
  400. /*        be a palette entry. Function enters each distinct     */
  401. /*                color as a palette entry and sets up the translation  */
  402. /*                table. It also shifts each color component left 3 bits*/
  403. /*                so that each color component is again 8 bits wide     */
  404. /*  Parameter   :                           */
  405. /*    blocks     - total number of pixel blocks                         */
  406. /*  Returns     : none                          */
  407. /*  Called by   : DFCimcomp()                       */
  408. /*  Calls       : indx()                        */
  409. /************************************************************************/
  410.  
  411. static void set_palette(blocks)
  412. int blocks;
  413. {
  414.   int ent, i, k;
  415.   int indx();
  416.  
  417.   ent = 0;
  418.   for (i = 0; i<(2*blocks); i++)
  419.   {
  420.     k = indx(color_pt[i].c[RED],color_pt[i].c[GREEN],color_pt[i].c[BLUE]);
  421.     if (trans[k] == -1)
  422.     {
  423.       new_pal[3*ent] = color_pt[i].c[RED] << 3;
  424.       new_pal[3*ent+1] = color_pt[i].c[GREEN] << 3;
  425.       new_pal[3*ent+2] = color_pt[i].c[BLUE] << 3;  
  426.       trans[k] = ent;
  427.       ent++;
  428.     }
  429.   }
  430. } /* end of set_palette */
  431.  
  432.  
  433.  
  434.  
  435.  
  436. /************************************************************************/
  437. /*  Function    : fillin_color                      */
  438. /*  Purpose : For each pixel block, fills in the pointers into the  */
  439. /*                palette.                                              */
  440. /*  Parameter   :                           */
  441. /*    blocks     - total number of pixel blocks             */
  442. /*  Returns     : none                          */
  443. /*  Called by   : DFCimcomp()                       */
  444. /*  Calls       : none                          */
  445. /************************************************************************/
  446.  
  447. static void fillin_color(blocks)
  448. int blocks;
  449. {
  450.   int i, j, k;
  451.  
  452.   for (i=0; i<blocks; i++)
  453.     for (j=HI; j<=LO; j++)
  454.     {
  455.       k = indx(color_pt[2*i+j].c[RED],color_pt[2*i+j].c[GREEN],
  456.            color_pt[2*i+j].c[BLUE]);
  457.       image[i*4+2+j] = trans[k];
  458.     }
  459. } /* end of fillin_color */
  460.  
  461.  
  462.  
  463.  
  464.  
  465. /************************************************************************/
  466. /*  Function    : indx                          */
  467. /*  Purpose : Maps an rgb triple (5 bits each) to an integer array  */
  468. /*        index                         */
  469. /*  Parameter   :                           */
  470. /*    r, g, b    - color components                 */
  471. /*  Returns     : returns an array index                */
  472. /*  Called by   : set_palette(), fillin_color(), map()                  */
  473. /*  Calls       : none                          */
  474. /************************************************************************/
  475.  
  476. static int indx(r, g, b)
  477. unsigned char r, g, b;
  478. {
  479.   int temp;
  480.  
  481.   temp = 0;
  482.   temp = ((r & 0x1f) << 10) | ((g & 0x1f)  << 5) | (b & 0x1f);
  483.   return temp;
  484. } /* end of indx */
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491. /************************************************************************/
  492. /*  Function    : map                           */
  493. /*  Purpose : Maps a color_pt to the closest representative color   */
  494. /*        Sets up translation table             */
  495. /*  Parameter   :                           */
  496. /*    blocks     - total number of pixel blocks             */
  497. /*  Returns     : none                          */
  498. /*  Called by   : DFCimcomp()                       */
  499. /*  Calls       : nearest_color()                   */
  500. /************************************************************************/
  501.  
  502. static void map(blocks)
  503. int blocks;
  504. {
  505.   int i, k;
  506.   unsigned char r, g, b;
  507.   int indx();
  508.   int nearest_color();
  509.  
  510.   for (i=0; i<(2*blocks); i++)
  511.   {
  512.     k = indx(color_pt[i].c[RED], color_pt[i].c[GREEN], color_pt[i].c[BLUE]);
  513.  
  514.     if (trans[k] == -1)
  515.     {
  516.       r = (unsigned char) color_pt[i].c[RED]<<3;
  517.       g = (unsigned char) color_pt[i].c[GREEN]<<3;
  518.       b = (unsigned char) color_pt[i].c[BLUE]<<3;
  519.       trans[k] = nearest_color(r, g, b);
  520. /*
  521.       printf("map: %d %d %d mapped to %d %d %d\n", r, g, b, new_pal[trans[k]*3],
  522.           new_pal[trans[k]*3+1], new_pal[trans[k]*3+2]);
  523. */
  524.     }
  525.   }
  526. } /* end of map */
  527.   
  528.  
  529.  
  530.  
  531. /************************************************************************/
  532. /*  Function    : nearest_color                     */
  533. /*  Purpose : Finds the nearest palette color           */
  534. /*  Parameter   :                           */
  535. /*    r, g, b    - color component                  */
  536. /*  Returns     : Entry number of the closest color in the palette      */
  537. /*  Called by   : map()                         */
  538. /*  Calls       : sqr()                         */
  539. /************************************************************************/
  540.  
  541. static int nearest_color(r, g, b)
  542. unsigned char r, g, b;
  543. {
  544.   int i, near; 
  545.   long int min, error;
  546.   long int sqr();
  547.  
  548.   min = sqr(r-new_pal[0]) + sqr(g-new_pal[1]) + sqr(b-new_pal[2]);
  549.   near = 0;
  550.   for (i=1; i<PALSIZE; i++)
  551.   {
  552.     error = sqr(r-new_pal[3*i]) + sqr(g-new_pal[3*i+1]) + 
  553.         sqr(b-new_pal[3*i+2]);
  554.     if (error < min)
  555.     {
  556.     min = error;
  557.         near = i;
  558.     }
  559.   }
  560.  
  561.   return near;
  562. } /* end of nearest_color */
  563.  
  564.  
  565.  
  566.  
  567. /************************************************************************/
  568. /*  Function    : sqr                           */
  569. /*  Purpose : Computes the square of an integer         */
  570. /*  Parameter   :                           */
  571. /*    x      - an integer                       */
  572. /*  Returns     : The square of x                   */
  573. /*  Called by   : nearest_color()                   */
  574. /*  Calls       : none                          */
  575. /************************************************************************/
  576.  
  577. static long int sqr(x)
  578. unsigned char x;
  579. {
  580.   return (x*x);
  581. }
  582.  
  583.  
  584.  
  585.  
  586.  
  587. /************************************************************************/
  588. /*  Function    : DFCunimcomp                       */
  589. /*  Purpose : 'Decompresses' the compressed image           */
  590. /*  Parameter   :                           */
  591. /*    xdim, ydim - dimensions of image                  */
  592. /*    in, out    - Input buffer and output buffer. Size of input buffer */
  593. /*         is (xdim*ydim)/4. Size of output buffer is 4 times   */
  594. /*         that. It 'restores' images into seq-type files       */
  595. /*  Returns     : none                          */
  596. /*  Called by   : External routines                 */
  597. /*  Calls       : none                          */
  598. /************************************************************************/
  599.  
  600. void DFCunimcomp(xdim, ydim, in, out)
  601. int32 xdim, ydim;
  602. char in[], out[];
  603. {
  604.   int bitmap, temp;
  605.   int i, j, k, x, y;
  606.   unsigned char hi_color, lo_color;
  607.  
  608.   for (y=0; y<(ydim/4); y++)
  609.     for (x=0; x<xdim; x=x+4)
  610.     {
  611.       k = y*xdim + x;
  612.       hi_color = (unsigned char) in[k+2]; 
  613.       lo_color = (unsigned char) in[k+3];
  614.  
  615.       bitmap = ((unsigned char)in[k] << 8) | (unsigned char)in[k+1];
  616.  
  617.       for (i=(y*4); i<(y*4+4); i++)
  618.       {
  619.         temp = bitmap >> (3 + y*4 - i)*4;
  620.         for (j=x; j<(x+4); j++)
  621.         {
  622.       if ((temp & 8) == 8)
  623.         out[i*xdim+j] = (char) hi_color;
  624.       else
  625.         out[i*xdim+j] = (char) lo_color;
  626.       temp = temp << 1;
  627.     }
  628.       }
  629.     } /* end of for x */
  630. } /* end of DFCunimcomp */
  631.  
  632.  
  633.  
  634. /************************************************************************/
  635. /*  Module Name : color                         */
  636. /*  Exports     : sel_palette(); new_pal, pointer to a new color palette*/
  637. /*  Purpose     : Quantizes colors                  */
  638. /*  Author  : Eng-Kiat Koh                      */
  639. /*  Date    : June 30th, 1988                   */
  640. /*  Functions   : sel_palette(), init(), sort(), partition(), find_box()*/
  641. /*        split_box(), assign_color(), select_dim(), find_med() */
  642. /*                classify(), next_pt()                                 */
  643. /************************************************************************/
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651. /************************************************************************/
  652. /*  Function    : sel_palette                       */
  653. /*  Purpose : Selects PALSIZE palette colors out of a list of colors*/
  654. /*        in color_pt                       */
  655. /*  Parameter   :                           */
  656. /*    blocks     - number of pixel blocks               */
  657. /*    distinct   - number of distinct colors                */
  658. /*    color_pt   - contains the lo hi colors for each pixel block       */
  659. /*  Returns     : none                          */
  660. /*  Called by   : DFCimcomp()                       */
  661. /*  Calls       : init(), split_box(), find_box(), assign_color()   */
  662. /************************************************************************/
  663.  
  664. static void sel_palette(blocks,distinct, color_pt)
  665. int blocks, distinct;
  666. struct rgb *color_pt;
  667. {
  668.   int boxes;
  669. /*  int i, j;*/
  670.   struct box *ptr;
  671.   struct box *find_box();
  672.   void init();
  673.   void split_box();
  674.   void assign_color();
  675.  
  676.   init(blocks, distinct, color_pt);
  677.  
  678.   /* split box into smaller boxes with about equal number of points */
  679.   for (boxes=1; boxes < PALSIZE; boxes++)
  680.   {
  681. /*
  682.     ptr=frontier->right;
  683.     j = 0;
  684.     while (ptr != NULL)
  685.     {
  686.       printf("Box %d, distinct %d, total %d\n",j,ptr->nmbr_distinct,
  687.              ptr->nmbr_pts);
  688.       for (i=0; i<ptr->nmbr_distinct; i++)
  689.         printf("pt %d: %d %d %d",i,distinct_pt[ptr->pts[i]].c[RED],
  690.                 distinct_pt[ptr->pts[i]].c[GREEN], 
  691.             distinct_pt[ptr->pts[i]].c[BLUE]);
  692.       j++;
  693.       ptr = ptr->right;
  694.     }
  695. */
  696.  
  697.     ptr = find_box();
  698.     split_box(ptr);
  699.   } 
  700.  
  701.   assign_color();
  702. }
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709. /************************************************************************/
  710. /*  Function    : init                          */
  711. /*  Purpose : Initializes the global variables, sets up the first   */
  712. /*        box. It will contain all the color points     */
  713. /*  Parameter   :                           */
  714. /*    blocks     - number of pixel blocks               */
  715. /*    distinct   - number of distinct colors                */
  716. /*    color_pt   - contains the lo hi colors for each pixel block       */
  717. /*  Returns     : none                          */
  718. /*  Called by   : sel_palette()                     */
  719. /*  Calls       : none                          */
  720. /************************************************************************/
  721.  
  722. static void init(blocks, distinct, color_pt)
  723. int blocks, distinct;
  724. struct rgb *color_pt;
  725. {
  726.   int i, j, k, l;
  727.   int temp[MAXCOLOR];
  728.   struct box *first;
  729.   struct box *dummy;
  730.  
  731.   /* alloc memory */
  732.   if (hist) DFIfreespace((char *) hist);
  733.   if (distinct_pt) DFIfreespace((char*) distinct_pt);
  734.   hist = (int *)DFIgetspace((unsigned)distinct * sizeof(int));
  735.   distinct_pt = (struct rgb *)DFIgetspace((unsigned)distinct *
  736.                       sizeof(struct rgb));
  737.  
  738.   for (i=0; i<distinct; i++)
  739.     hist[i] = 0;
  740.  
  741.  
  742.   /* select distinct pts and set up histogram */
  743.   for (i=0; i<MAXCOLOR; i++)
  744.     temp[i] = -1;
  745.  
  746.   k = 0;
  747.   for (i=0; i<(2*blocks); i++)
  748.   {
  749.     j = (color_pt[i].c[RED] << 10) | (color_pt[i].c[GREEN] << 5) |
  750.         color_pt[i].c[BLUE];
  751.  
  752.     if (temp[j] == -1)
  753.     {
  754.       /* new pt */
  755.       temp[j] = k;
  756.       for (l=RED; l<=BLUE; l++)
  757.     distinct_pt[k].c[l] = color_pt[i].c[l];
  758.       k++;
  759.    }
  760.  
  761.    hist[temp[j]]++;
  762.   }
  763.  
  764.       
  765.   /* set up first box */
  766.   first = (struct box *)DFIgetspace(sizeof(struct box));
  767.   for (i=RED; i<=BLUE; i++)
  768.   {
  769.     first->bnd[i][LO] = 999.9;
  770.     first->bnd[i][HI] = -999.9;
  771.  
  772.     for (j=0; j<distinct; j++)
  773.     {
  774.       if (first->bnd[i][LO] > (float)distinct_pt[j].c[i])
  775.     first->bnd[i][LO] = (float)distinct_pt[j].c[i];
  776.  
  777.       if (first->bnd[i][HI] < (float)distinct_pt[j].c[i])
  778.     first->bnd[i][HI] = (float)distinct_pt[j].c[i];
  779.     } /* end of for j */
  780.  
  781.     first->bnd[i][LO] = first->bnd[i][LO] - EPSILON;
  782.     first->bnd[i][HI] = first->bnd[i][HI] + EPSILON;
  783.   } /* end of for i */
  784.  
  785.   first->pts = (int *)DFIgetspace((unsigned)distinct * sizeof(int));
  786.   for (i=0; i<distinct; i++)
  787.     first->pts[i] = i;
  788.   first->nmbr_pts = 2*blocks;
  789.   first->nmbr_distinct = distinct;
  790.  
  791.   dummy = (struct box *)DFIgetspace(sizeof(struct box));
  792.   frontier = dummy;
  793.   dummy->right = first;
  794.   first->left = dummy;
  795.   first->right = NULL;
  796.   dummy->nmbr_pts = 0;
  797.  
  798.   DFIfreespace((char *)first);
  799.   DFIfreespace((char *)dummy);
  800. } /* end of init */
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.  
  808. /************************************************************************/
  809. /*  Function    : sort                          */
  810. /*  Purpose : Performs quick sort on the points in a box along a    */
  811. /*        given dimension                   */
  812. /*  Parameter   :                           */
  813. /*    l, r   - index of leftmost and rightmost element      */
  814. /*    dim    - dimension along which sorting is done        */
  815. /*    rank   - an array which carries the index of the points to be */
  816. /*         sorted                       */
  817. /*  Returns     : none                          */
  818. /*  Called by   : find_med()                        */
  819. /*  Calls       : partition()                       */
  820. /************************************************************************/
  821.  
  822. static void sort(l,r,dim, rank)
  823. int l, r, dim, rank[];
  824. {
  825.   int i;
  826.   int partition();
  827.   void sort();
  828.  
  829.   if (r > l)
  830.   {
  831.     i = partition(l, r, dim, rank);
  832.     sort(l, i-1, dim, rank);
  833.     sort(i+1, r, dim, rank);
  834.   }
  835. }
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842. /************************************************************************/
  843. /*  Function    : partition                     */
  844. /*  Purpose : Partitions the list into 2 parts as in the quick sort */
  845. /*        algorithm                     */
  846. /*  Parameter   :                           */
  847. /*    l, r   - index of leftmost and rightmost element      */
  848. /*    dim    - dimension along which sorting is done        */
  849. /*    rank   - an array which carries the index of the points to be */
  850. /*  Returns     : index where list is partitioned           */
  851. /*  Called by   : sort()                        */
  852. /*  Calls       : none                          */
  853. /************************************************************************/
  854.  
  855. static int partition(l, r, dim, rank)
  856. int l, r, dim, rank[];
  857. {
  858.   int i, j, temp;
  859.   char v;
  860.   
  861.   v = distinct_pt[rank[r]].c[dim];
  862.   i = l-1;
  863.   j = r;
  864.  
  865.   /* repeat until i and j crosses */
  866.   do
  867.   {
  868.     /* repeat until an element >= v is found */
  869.     do
  870.       i++;
  871.     while (distinct_pt[rank[i]].c[dim] < v);
  872.  
  873.     /* repeat until an element <= v is found */
  874.     do
  875.       j--;
  876.     while ((j>0) && (distinct_pt[rank[j]].c[dim] > v));
  877.  
  878.     /* swap pointers */
  879.     temp = rank[i];
  880.     rank[i] = rank[j];
  881.     rank[j] = temp;
  882.   }
  883.   while (i < j);
  884.  
  885.   /* position partitioning element at location i */
  886.   temp = rank[j];
  887.   rank[j] = rank[i];
  888.   rank[i] = rank[r];
  889.   rank[r] = temp;
  890.  
  891.   return i;
  892. }
  893.  
  894.  
  895.  
  896.  
  897.  
  898. /************************************************************************/
  899. /*  Function    : find_box                      */
  900. /*  Purpose : Finds the box with the largest number of color points */
  901. /*        The points need not necessarily be distinct. But in   */
  902. /*        order to partition the box, there must be at least  2 */
  903. /*        distinct points                   */
  904. /*  Parameter   : none                          */
  905. /*  Returns     : pointer to box selected for splitting         */
  906. /*  Called by   : sel_palette()                     */
  907. /*  Calls       : none                          */
  908. /************************************************************************/
  909.  
  910. static struct box *find_box()
  911. {
  912.   struct box *temp;
  913.   struct box *max;
  914.   int max_pts;
  915.  
  916.   max_pts = 1;
  917.   max = NULL;
  918.   temp = frontier->right;
  919.   while (temp != NULL)
  920.     if ((temp->nmbr_distinct > 1) && (max_pts < temp->nmbr_pts))
  921.     {
  922.       max_pts = temp->nmbr_pts;
  923.       max = temp;
  924.       temp = temp->right;
  925.     }
  926.     else
  927.       temp = temp->right;
  928.  
  929.   if (max == NULL)
  930.   {
  931.     printf("Error : Number of color points < palette \n");
  932.     exit(1);
  933.   }
  934.  
  935.   return max;
  936. }
  937.  
  938.  
  939.  
  940.  
  941.  
  942. /************************************************************************/
  943. /*  Function    : split_box                     */
  944. /*  Purpose : Splits a selected box into 2 and reinserts the 2 sub- */
  945. /*        boxes into the frontier list              */
  946. /*  Parameter   :                           */
  947. /*    ptr    - pointer to box to be split               */
  948. /*  Returns     : none                          */
  949. /*  Called by   : sel_palette()                     */
  950. /*  Calls       : find_med(), select_dim(), classify()          */
  951. /************************************************************************/
  952.  
  953. static void split_box(ptr)
  954. struct box *ptr;
  955. {
  956.   int dim, j, i;
  957.   float median;
  958.   struct box *l_child, *r_child;
  959.   int select_dim();
  960.   float find_med();
  961.   void classify();
  962.   
  963.   dim = select_dim(ptr);
  964.   median = find_med(ptr, dim);
  965.  
  966.   /* create 2 child */
  967.   l_child = (struct box *)DFIgetspace(sizeof(struct box));
  968.   r_child = (struct box *)DFIgetspace(sizeof(struct box));
  969.   
  970.   for (i=RED; i<=BLUE; i++)
  971.     for (j=HI; j<=LO; j++)
  972.     {
  973.       l_child->bnd[i][j] = ptr->bnd[i][j];
  974.       r_child->bnd[i][j] = ptr->bnd[i][j];
  975.     }
  976.   l_child->bnd[dim][HI] = median;
  977.   r_child->bnd[dim][LO] = median;
  978.  
  979.   classify(ptr,l_child);
  980.   classify(ptr,r_child);
  981.  
  982.   r_child->right = ptr->right;
  983.   r_child->left = l_child;
  984.   l_child->right = r_child;
  985.   l_child->left = ptr->left;
  986.   (ptr->left)->right = l_child;
  987.   if (ptr->right != NULL)
  988.     (ptr->right)->left = r_child;
  989. } /* end of split_box */
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996. /************************************************************************/
  997. /*  Function    : assign_color                      */
  998. /*  Purpose : Assigns a color to each box. It computes the average  */
  999. /*        color of all the points in the box            */
  1000. /*        Sets up the new_pal buffer. Each color component is   */
  1001. /*        shifted left 3 bits because of the truncation when    */
  1002. /*        color_pt was set up                   */
  1003. /*  Parameter   : none                          */
  1004. /*  Returns     : none                          */
  1005. /*  Called by   : sel_palette()                     */
  1006. /*  Calls       : none                          */
  1007. /************************************************************************/
  1008.  
  1009.  
  1010. static void assign_color()
  1011. {
  1012.   struct box *temp;
  1013.   int ent, k, j;
  1014.   int c[3];
  1015.  
  1016.   temp = frontier->right;
  1017.   for (ent=0; ent<PALSIZE; ent++)
  1018.   {
  1019.     for (k=RED; k<=BLUE; k++)
  1020.       c[k] = 0;
  1021.  
  1022. /*
  1023.     printf("Box %d: number of pts %d\n", ent, temp->nmbr_pts);
  1024. */
  1025.  
  1026.     for (j=0; j<temp->nmbr_distinct; j++)
  1027.     {
  1028. /*
  1029.       printf("pt %d:", j);
  1030. */
  1031.       for (k=RED; k<=BLUE; k++)
  1032.       {
  1033. /*
  1034.         printf("%d ",distinct_pt[temp->pts[j]].c[k]);
  1035. */
  1036.     c[k] = c[k] + distinct_pt[temp->pts[j]].c[k]*hist[temp->pts[j]];
  1037.       }
  1038. /*
  1039.       printf("\n");
  1040. */
  1041.     }
  1042.  
  1043.     for (k=RED; k<=BLUE; k++)
  1044.     {
  1045.       c[k] = c[k] / temp->nmbr_pts;
  1046.       new_pal[3*ent+k] = c[k] << 3;
  1047.     }
  1048.     
  1049.     temp = temp->right;
  1050.   } /* end of for entry */
  1051. }
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057. /************************************************************************/
  1058. /*  Function    : select_dim                        */
  1059. /*  Purpose : Selects the dimension with the largest spread         */
  1060. /*  Parameter   :                           */
  1061. /*    ptr    - pointer to desired box               */
  1062. /*  Returns     : dimension where the box is to be split        */
  1063. /*  Called by   : split_box()                       */
  1064. /*  Calls       : none                          */
  1065. /************************************************************************/
  1066.  
  1067. static int select_dim(ptr)
  1068. struct box *ptr;
  1069. {
  1070.   int i, j, low[3], high[3];
  1071.   int max;
  1072.  
  1073.  
  1074.   for (j=RED; j<=BLUE; j++)
  1075.   {
  1076.     low[j] = distinct_pt[ptr->pts[0]].c[j];
  1077.     high[j] = distinct_pt[ptr->pts[0]].c[j];
  1078.   }
  1079.  
  1080.   for (i=1; i<ptr->nmbr_distinct; i++)
  1081.     for (j=RED; j<=BLUE; j++)
  1082.     {
  1083.       if (low[j] > distinct_pt[ptr->pts[i]].c[j])
  1084.     low[j] = distinct_pt[ptr->pts[i]].c[j];
  1085.       if (high[j] < distinct_pt[ptr->pts[i]].c[j])
  1086.     high[j] = distinct_pt[ptr->pts[i]].c[j];
  1087.     }
  1088.  
  1089.   max = high[RED] - low[RED];
  1090.   i = RED;
  1091.   for (j=GREEN; j<=BLUE; j++)
  1092.     if (max < (high[j] - low[j]))
  1093.     {
  1094.       max = high[j] - low[j];
  1095.       i = j;
  1096.     }
  1097.  
  1098.   return i;
  1099. } /* end of select_dim */
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105. /************************************************************************/
  1106. /*  Function    : find_med                      */
  1107. /*  Purpose : Finds the point where the box is to be split. It finds*/
  1108. /*        a point such that the 2 new boxes have about the same */
  1109. /*        number of color points.               */
  1110. /*  Parameter   :                           */
  1111. /*    ptr    - pointer to box to be split               */
  1112. /*    dim    - dimension to split box               */
  1113. /*  Returns     : point where the box is to be cut          */
  1114. /*  Called by   : split_box()                       */
  1115. /*  Calls       : next_pt()                     */
  1116. /************************************************************************/
  1117.  
  1118. static float find_med(ptr,dim)
  1119. struct box *ptr;
  1120. int dim;
  1121. {
  1122.   int i, j, count, next, prev;
  1123.   int *rank;
  1124.   float median;
  1125.   int next_pt();
  1126.   void sort();
  1127.  
  1128.   rank = (int *)DFIgetspace((unsigned)ptr->nmbr_distinct * sizeof(int));
  1129.   for (i=0; i<ptr->nmbr_distinct; i++)
  1130.     rank[i] = ptr->pts[i];
  1131.  
  1132.   sort(0,ptr->nmbr_distinct-1,dim,rank);
  1133. /*
  1134.   for (i=0; i<ptr->nmbr_distinct; i++)
  1135.     printf("find_med: sorted list is %d\n",distinct_pt[rank[i]].c[dim]);
  1136. */
  1137.   
  1138.  
  1139.   count = 0;
  1140.   i = 0;
  1141.   while ((i < ptr->nmbr_distinct) && (count < ptr->nmbr_pts/2))
  1142.   {
  1143.     next = next_pt(dim, i, rank, ptr->nmbr_distinct);
  1144.     for (j=i; j<next; j++)
  1145.       count = count + hist[rank[j]];
  1146.  
  1147.     prev = i;
  1148.     i = next; 
  1149.   }
  1150.  
  1151.   if (prev == 0)
  1152.   {
  1153.     /* the first distinct point overshot the median */
  1154.     median = (float)distinct_pt[rank[prev]].c[dim] + EPSILON;
  1155.   }
  1156.   else
  1157.     median = (float)distinct_pt[rank[prev-1]].c[dim] + EPSILON;
  1158.    
  1159.   DFIfreespace((char *) rank);
  1160.   return median;
  1161. } /* end of find_med */
  1162.   
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168. /************************************************************************/
  1169. /*  Function    : classify                      */
  1170. /*  Purpose : Looks at the color points in the parent and selects   */
  1171. /*        the points that belong to the child           */
  1172. /*  Parameter   :                           */
  1173. /*    ptr    - pointer to parent                    */
  1174. /*    child  - pointer to child box                 */
  1175. /*  Returns     : none                          */
  1176. /*  Called by   : split_box()                       */
  1177. /*  Calls       : none                          */
  1178. /************************************************************************/
  1179.  
  1180. static void classify(ptr, child)
  1181. struct box *ptr, *child;
  1182. {
  1183.   int i, j;
  1184.   int *temp;
  1185.   int distinct, total;
  1186.  
  1187.   temp = (int *)DFIgetspace((unsigned)ptr->nmbr_distinct * sizeof(int));
  1188.  
  1189.   distinct = 0;
  1190.   total = 0;
  1191.   for (i=0; i<ptr->nmbr_distinct; i++)
  1192.   {
  1193.     j = ptr->pts[i];
  1194.     if ((((float)distinct_pt[j].c[RED] >= child->bnd[RED][LO]) &&
  1195.          ((float)distinct_pt[j].c[RED] <= child->bnd[RED][HI])) &&
  1196.         (((float)distinct_pt[j].c[GREEN] >= child->bnd[GREEN][LO]) &&
  1197.          ((float)distinct_pt[j].c[GREEN] <= child->bnd[GREEN][HI])) &&
  1198.         (((float)distinct_pt[j].c[BLUE] >= child->bnd[BLUE][LO]) &&
  1199.          ((float)distinct_pt[j].c[BLUE] <= child->bnd[BLUE][HI])))
  1200.     {
  1201.       /* pt is in new box */
  1202.       temp[distinct] = j;
  1203.       distinct++;
  1204.       total = total + hist[j];
  1205.     } /* end of if */
  1206.   } /* end of for i */
  1207.  
  1208.   /* assign points */
  1209.   child->nmbr_pts = total;
  1210.   child->nmbr_distinct = distinct;
  1211.   child->pts = (int *)DFIgetspace((unsigned)distinct * sizeof(int));
  1212.   for (i=0; i<distinct; i++)
  1213.     child->pts[i] = temp[i];
  1214.  
  1215.   DFIfreespace((char *)temp);
  1216.  
  1217. } /* end of classify */
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223. /************************************************************************/
  1224. /*  Function    : next_pt                       */
  1225. /*  Purpose : Determines the next point that has a different value  */
  1226. /*        from the current point along  a dimension     */
  1227. /*  Parameter   :                           */
  1228. /*    dim    - dimension where box is to be split           */
  1229. /*    i      - index to current point               */
  1230. /*    rank       - sorted list of points to be searched starting from i */
  1231. /*    distinct   - length of sorted list                                */
  1232. /*  Returns     : index of point that has a different value     */
  1233. /*  Called by   : find_med                      */
  1234. /*  Calls       : none                          */
  1235. /************************************************************************/
  1236.  
  1237. static int next_pt(dim, i, rank, distinct)
  1238. int dim, i, rank[], distinct;
  1239. {
  1240.   int j;
  1241.   char old;
  1242.  
  1243.   old = distinct_pt[rank[i]].c[dim];
  1244.   for (j=(i+1); j<distinct; j++)
  1245.     if (distinct_pt[rank[j]].c[dim] != old)
  1246.       break;
  1247.  
  1248.   return j;
  1249. } /* end of next_pt */
  1250.  
  1251.